//! 管理部门
use super::SysFilter;
use crate::{
    error::{AppError, AppResult},
    extract::{Json, ValJson},
    security::LoginUser,
    AppState,
};
use ane_system::dao::{self, dept::DeptDo, Dept2Vo, DeptDetailVo};
use axum::{
    extract::{Path, Query},
    response::IntoResponse,
    routing::get,
    Extension, Router,
};
use loginmanager::AuthUser;
use tracing_subscriber::fmt::format;
use validator::Validate;

/// [Dept](ane_system::entity::sys_dept)操作相关的路由
/// - `{prefix}/` `GET|POST` [Dept](ane_system::entity::sys_dept)的查询和创建
/// - `{prefix}/:id` `GET|PUT|DELETE` [Dept](ane_system::entity::sys_dept)的获取、更新和删除
pub fn get_route<S>(prefix: &str) -> Router<S>
where
    S: Sync + Send + Clone + 'static,
{
    let f = move |p: &str| -> String { format!("{}{p}", prefix) };
    Router::<S>::new()
        .route(&f("/"), get(tree_table).post(create))
        .route(&f("/:id"), get(fetch_one).put(update).delete(delete))
}

#[inline]
pub async fn create(
    Extension(state): Extension<AppState>,
    user: LoginUser,
    ValJson(data): ValJson<DeptDo>,
) -> AppResult<impl IntoResponse> {
    if let Some(p_id) = data.parent_id {
        // 检查是否可以访问单位
        if !user.can_access_dept_id(state.db(), p_id).await? {
            Err(AppError::Forbidden)?
        };
    } else {
        Err(AppError::MissParam("miss parent_id".to_owned()))?;
    }
    dao::Dept::create(state.db(), data)
        .await
        .map(Json)
        .map_err(Into::into)
}

/// 获得id单位的详细信息[DeptDetailVo]
pub async fn fetch_one(
    Extension(state): Extension<AppState>,
    Path(id): Path<i32>,
    user: LoginUser,
) -> AppResult<impl IntoResponse> {
    // 检查是否可以访问单位
    if !user.can_access_dept_id(state.db(), id).await? {
        Err(AppError::Forbidden)?
    };

    dao::Dept::get_by_id::<DeptDetailVo>(state.db(), id, None, Some(false))
        .await
        .map(Json)
        .map_err(Into::into)
}

pub async fn update(
    Extension(state): Extension<AppState>,
    Path(id): Path<i32>,
    user: LoginUser,
    ValJson(mut data): ValJson<DeptDo>,
) -> AppResult<impl IntoResponse> {
    // 禁止修改根单位和用户自己单位的status和parent_id
    if id == 1 || id == user.d_id {
        data.status = Some(true);
        data.parent_id = None;
        data.order_num = None;
    };
    // 检查是否可以访问单位
    if !user.can_access_dept_id(state.db(), id).await? {
        Err(AppError::Forbidden)?
    };
    // 检查是否可以访问单位
    if matches!(data.parent_id, Some(id) if !user.can_access_dept_id(state.db(), id).await?) {
        Err(AppError::Forbidden)?
    };

    dao::Dept::update(state.db(), id, data)
        .await
        .map(Json)
        .map_err(Into::into)
}

pub async fn delete(
    Extension(state): Extension<AppState>,
    Path(id): Path<i32>,
    user: LoginUser,
) -> AppResult<impl IntoResponse> {
    // 禁止删除根单位和用户自己的单位
    if id == 1 || id == user.d_id {
        return Err(AppError::Forbidden);
    };
    // 检查是否可以访问单位
    if !user.can_access_dept_id(state.db(), id).await? {
        Err(AppError::Forbidden)?
    };

    dao::Dept::soft_delete(state.db(), id)
        .await
        .map_err(Into::into)
        .map(|_| "Ok")
}

/// 获得单位的树结构
/// ## query参数
/// - status  单位状态 true正常 false停用 None不筛选
pub async fn tree_table(
    Extension(state): Extension<AppState>,
    Query(filter): Query<SysFilter>,
    user: LoginUser,
) -> AppResult<impl IntoResponse> {
    let (id, remove) = match user.data_scope() {
        1 => (1, false),
        3 => (user.d_id, false),
        _ => (user.d_id, true),
    };
    dao::Dept::get_tree(state.db(), id, filter.status)
        .await
        .map(|f| {
            f.map(|mut f| {
                if remove {
                    f.children = None;
                }
                f
            })
        })
        .map(Json)
        .map_err(Into::into)
}
